﻿#region Header
// Copyright 2007-2011, Jerónimo Milea
// 
// This file is part of NetJsWire.
// 
//     NetJsWire is free software: you can redistribute it and/or modify
//     it under the terms of the GNU General Public License as published by
//     the Free Software Foundation, either version 3 of the License, or
//     (at your option) any later version.
// 
//     NetJsWire is distributed in the hope that it will be useful,
//     but WITHOUT ANY WARRANTY; without even the implied warranty of
//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//     GNU General Public License for more details.
// 
//     You should have received a copy of the GNU General Public License
//     along with NetJsWire.  If not, see <http://www.gnu.org/licenses/>.
#endregion

using System;
using System.Web;
using System.Web.SessionState;
using NetJsWire.JsonRpcHandler.Handlers;
using NetJsWire.JsonRpcHandler.Util;
using Newtonsoft.Json;

namespace NetJsWire.JsonRpcHandler.RealAsync
{
    public class AsyncHandler : IHttpAsyncHandler, IRequiresSessionState
    {
        private static readonly ThreadPool ThreadPool;
        private readonly bool _imageHandler;

        static AsyncHandler()
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;

            ThreadPool = new ThreadPool( 2, 25, "AsyncPool" )
                             {
                                 PropogateCallContext = true,
                                 PropogateThreadPrincipal = true,
                                 PropogateHttpContext = true
                             };
            ThreadPool.Start();
        }

        public AsyncHandler( bool image )
        {
            _imageHandler = image;
        }

        #region IHttpAsyncHandler Members

        public void ProcessRequest( HttpContext ctx )
        {
            // not used
        }

        public bool IsReusable
        {
            get { return false; }
        }

        public IAsyncResult BeginProcessRequest( HttpContext ctx, AsyncCallback cb, object obj )
        {
            var reqState = new AsyncRequestState( ctx, cb, obj );
            ThreadPool.PostRequest( new WorkRequestDelegate( ProcessRequest ), reqState );

            return reqState;
        }

        public void EndProcessRequest( IAsyncResult ar )
        {
        }

        #endregion

        private static void CurrentDomainUnhandledException( object sender, UnhandledExceptionEventArgs e )
        {
            WebApplication.Instance.OnUnhandledException( sender, e );
        }

        private void ProcessRequest( object state, DateTime requestTime )
        {
            var reqState = state as AsyncRequestState;
            if ( _imageHandler )
            {
                if ( reqState != null )
                {
                    var imageProcessor = new ImageRequestProcessor( reqState.Ctx );
                    try
                    {
                        imageProcessor.Process();
                    }
                    catch ( Exception )
                    {
                        //TODO: Comented code because exception handling on client is not ready to manage failed image loads, needs some love...
                        //var exeText = e.InnerException != null
                        //                     ? e.InnerException.Message.Replace( Environment.NewLine, "<br />" )
                        //                     : e.Message.Replace( Environment.NewLine, "<br />" );
                        //var stackTrace = e.InnerException != null
                        //                        ? Jayrock.Json.Conversion.JsonConvert.ExportToString(
                        //                                                                             e.InnerException.StackTrace )
                        //                        : Jayrock.Json.Conversion.JsonConvert.ExportToString( e.StackTrace );
                        //TODO: Implement exception Dialog on server???...
                        //if ( imageProcessor != null )
                        //{
                        //    //if (WebApplication.Instance == null)
                        //    //    reqState._ctx.Response.Write(Jayrock.Json.Conversion.JsonConvert.ExportToString(new JSONRpcResult(p.Post.id, "ShowException(\"Session ended.\",\"The session has ended on server, press F5 to reload.\");", null)));
                        //    //else
                        //    //    reqState._ctx.Response.Write(Jayrock.Json.Conversion.JsonConvert.ExportToString(new JSONRpcResult(p.Post.id, "ShowException(\"" + exeText + "\",\"" + stackTrace.Replace("[", "").Replace("]", "") + "\");", null)));
                        //}
                        //else
                        //{
                        //    reqState._ctx.Response.Write(
                        //                                 Jayrock.Json.Conversion.JsonConvert.ExportToString( new JSONRpcResult( "-1",
                        //                                                                                                        "ShowException(\"" +
                        //                                                                                                        exeText + "\",\"" +
                        //                                                                                                        stackTrace.Replace(
                        //                                                                                                                           "[", "" ).Replace
                        //                                                                                                            ( "]", "" ) +
                        //                                                                                                        "\");", null ) ) );
                        //}
                    }
                    finally
                    {
                        reqState.CompleteRequest();
                    }
                }
            }
            else
            {
                if ( reqState != null )
                {
                    var p = new CSJsonRequestProcessor( reqState.Ctx );
                    try
                    {
                        p.Process();
                    }
                    catch ( Exception e )
                    {
                        var exeText = e.InnerException != null
                                             ? e.InnerException.Message.Replace( Environment.NewLine, "<br />" )
                                             : e.Message.Replace( Environment.NewLine, "<br />" );
                        var stackTrace = e.InnerException != null
                                                ? e.InnerException.StackTrace
                                                : e.StackTrace;
                        stackTrace = JsonConvert.ToString( stackTrace.Replace( Environment.NewLine, "<br />" ) );
                        if ( WebApplication.Instance.IsNull )
                            reqState.Ctx.Response.Write(
                                                         JsonConvert.SerializeObject( new JSONRpcResult( "-1",
                                                                                                                                string.Format( "ShowException('{0}','{1}');", WebApplication.SessionEndedErrorTitle, WebApplication.SessionEndedErrorText ),
                                                                                                                                null ) ) );
                        else
                            reqState.Ctx.Response.Write(
                                                         JsonConvert.SerializeObject( new JSONRpcResult( "-1",
                                                                                                                                string.Format( "ShowException('{0}','{1}'",
                                                                                                                                               exeText,
                                                                                                                                               stackTrace ), null ) ) );
                    }
                    finally
                    {
                        reqState.CompleteRequest();
                    }
                }
            }
        }
    }
}